home *** CD-ROM | disk | FTP | other *** search
/ Collection of Tools & Utilities / Collection of Tools and Utilities.iso / comm / com_pkg1.zip / COM_PKG1.ASM next >
Assembly Source File  |  1984-04-20  |  12KB  |  433 lines

  1.     title    COM_PKG1
  2.     page    60,132
  3. ;
  4. ; COM_PKG1.ASM library of serial I/O routines
  5. ; For the IBM PC's first serial port
  6. ; Uses Microsoft Pascal calling conventions
  7. ; See GLASSTTY.PAS for sample driver program
  8. ;
  9. ; Adapted from code by John Romkey and Jerry Saltzer of MIT
  10. ; by Richard Gillmann (GILLMANN@ISIB), 1983
  11. ;
  12. ; Package entry points (MS Pascal calling conventions) are:
  13. ;
  14. ; init_au(divisor:word)    initializes port and interrupt vector
  15. ; close_a        turns off interrupts from the aux port
  16. ; dtr_off        turns off dtr
  17. ; dtr_on        turns on dtr
  18. ; crcnt : word        returns number of characters in input buffer
  19. ; cread : byte        reads next character in input buffer
  20. ; cwcnt : word        returns number of free bytes in output buffer
  21. ; cwrit(ch:byte)    writes a character to the output buffer
  22. ; wlocal(ch:byte)    writes a character to the input buffer
  23. ; make_br        causes a break to be sent
  24. ;
  25.     page
  26. rsize    equ    2048        ; size of receive buffer
  27. tsize    equ    256        ; size of transmit buffer
  28. base    equ    3f0h        ; base of address of aux. port registers
  29. int    equ    0ch        ; interrupt number for aux port
  30. int_off    equ    int*4        ; offset of interrupt vector
  31. datreg    equ    base + 8h    ; data register
  32. dll    equ    base + 8h    ; low divisor latch
  33. dlh    equ    base + 9h    ; high divisor latch
  34. ier    equ    base + 9h    ; interrupt enable register
  35. iir    equ    base + 0ah    ; interrupt identification register
  36. lcr    equ    base + 0bh    ; line control register
  37. mcr    equ    base + 0ch    ; modem control register
  38. lsr    equ    base + 0dh    ; line status register
  39. msr    equ    base + 0eh    ; modem status register
  40. dla    equ    80h        ; divisor latch access
  41. mode    equ    03h        ; 8-bits, no parity
  42. dtr    equ    0bh        ; bits to set dtr line
  43. dtr_of    equ    00h        ; turn off dtr, rts, and the interupt driver
  44. thre    equ    20h        ; mask to find status of xmit holding register
  45. rxint    equ    01h        ; enable data available interrupt
  46. txint    equ    02h        ; enable tx holding register empty interrupt
  47. tcheck    equ    20h        ; mask for checking tx reg status on interrupt
  48. rcheck    equ    01h        ; mask for checking rx reg status on interrupt
  49. imr    equ    21h        ; interuprt mask register
  50. int_mask equ    0efh        ; mask to clear bit 4
  51. int_pend equ    01h        ; there is an interrupt pending
  52. mstat    equ    00h        ; modem status interrupt
  53. wr    equ    02h        ; ready to xmit data
  54. rd    equ    04h        ; received data interrupt
  55. lstat    equ    06h        ; line status interrupt
  56. ack    equ    244        ; acknowledge symbol
  57. parity    equ    7fh        ; bits to mask off parity
  58. ocw2    equ    20h        ; operational control word on 8259
  59. eoi    equ    64h        ; specific end of interrupt 4
  60. break    equ    40h        ; bits to cause break
  61. true    equ    1        ; truth
  62. false    equ    0        ; falsehood
  63.     page
  64. data    segment public 'data'
  65. int_offset    dw    0    ; the original interrupt offset
  66. int_segment    dw    0    ; the original interrupt segment
  67. start_tdata    dw    0    ; index to first character in x-mit buffer
  68. end_tdata    dw    0    ; index to first free space in x-mit buffer
  69. size_tdata    dw    0    ; number of characters in x-mit buffer
  70. start_rdata    dw    0    ; index to first character in rec. buffer
  71. end_rdata    dw    0    ; index to first free space in rec. buffer
  72. size_rdata    dw    0    ; number of characters in rec. buffer
  73. tdata        db    tsize dup(?)    ; transmit buffer
  74. rdata        db    rsize dup(?)    ; receive buffr
  75. data    ends
  76. dgroup    group    data
  77.     page
  78.     assume    cs:auxhndlr,ds:dgroup,ss:dgroup
  79. auxhndlr segment 'code'
  80.  
  81.     public    init_au        ; initializes port and interrupt vector
  82.     public    close_a        ; turns off interrupts from the aux port
  83.     public    dtr_off        ; turns off dtr
  84.     public    dtr_on        ; turns on dtr
  85.     public    crcnt        ; returns number of characters in input buffer
  86.     public    cread        ; reads next character in input buffer
  87.     public    cwcnt        ; returns no. of free bytes in output buffer
  88.     public    cwrit        ; writes a character to output buffer
  89.     public    wlocal        ; writes a character to the input buffer
  90.     public    make_br        ; causes a break to be sent
  91.     page
  92. ;
  93. ; int_hndlr - handles interrupts generated by the aux. port
  94. ;
  95. dataseg    dw    0
  96. int_hndlr proc    far
  97.     push    bp
  98.     push    ds
  99.     push    di
  100.     push    ax
  101.     push    bx
  102.     push    cx
  103.     push    dx
  104.  
  105. ; set up data segment
  106.     mov    ax,cs:dataseg
  107.     mov    ds,ax
  108.  
  109. ; find out where interrupt came from and jump to routine to handle it
  110.     mov     dx,iir
  111.     in    al,dx
  112.     cmp     al,rd
  113.     jz      rx_int        ; if it's from the receiver
  114.     cmp     al,wr
  115.     jz      tx_int          ; if it's from the transmitter
  116.     cmp     al,lstat
  117.     jz      lstat_int       ; interrupt becuase of line status
  118.     cmp     al,mstat
  119.     jz      mstat_int       ; interrupt because of modem status
  120.     jmp     far ptr int_end    ; interrupt when no interrupt pending, go away
  121.  
  122. lstat_int:
  123.     mov     dx,lsr        ; clear interrupt
  124.     in    al,dx
  125.     jmp     repoll        ; see if any more interrupts
  126.  
  127. mstat_int:
  128.     mov     dx,msr        ; clear interrupt
  129.     in    al,dx
  130.     jmp     repoll          ; see if any more interrupts
  131.  
  132. tx_int:
  133.     mov     dx,lsr
  134.     in    al,dx
  135.     and     al,tcheck
  136.     jnz     goodtx          ; good interrupt
  137.     jmp     repoll          ; see if any more interrupts
  138.  
  139. goodtx: cmp     size_tdata,0    ; see if any more data to send
  140.     jne     have_data       ; if not equal then there is data to send
  141.  
  142. ; if no data to send then reset tx interrupt and return
  143.     mov     dx,ier
  144.     mov     al,rxint
  145.     out    dx,al
  146.     jmp     repoll
  147.  
  148. have_data:
  149.     mov     bx,start_tdata    ; bx points to next char. to be sent
  150.     mov     dx,datreg    ; dx equals port to send data to
  151.     mov     al,tdata[bx]    ; get data from buffer
  152.     out     dx,al        ; send data
  153.     inc     bx              ; increment start_tdata
  154.     cmp     bx,tsize    ; see if gone past end
  155.     jl      ntadj           ; if not then skip
  156.     sub     bx,tsize    ; reset to beginning
  157. ntadj:  mov     start_tdata,bx  ; save start_tdata
  158.     dec     size_tdata      ; one less character in x-mit buffer
  159.     jmp     repoll
  160.  
  161. rx_int:
  162.     mov     dx,lsr        ; check and see if read is real
  163.     in    al,dx
  164.     and     al,rcheck    ; look at receive data bit
  165.     jnz     good_rx         ; real, go get byte
  166.     jmp     repoll          ; go look for other interrupts
  167.  
  168. good_rx:
  169.     mov     dx,datreg
  170.     in      al,dx        ; get data
  171.     cmp     size_rdata,rsize    ; see if any room
  172.     jge    repoll          ; if no room then look for more interrupts
  173.     mov     bx,end_rdata    ; bx points to free space
  174.     mov     rdata[bx],al    ; send data to buffer
  175.     inc     size_rdata      ; got one more character
  176.     inc     bx              ; increment end_rdata pointer
  177.     cmp     bx,rsize    ; see if gone past end
  178.     jl      nradj           ; if not then skip
  179.     sub     bx,rsize    ; else adjust to beginning
  180. nradj:  mov     end_rdata,bx    ; save value
  181.  
  182. repoll:
  183.     mov     dx,lsr        ; we always expect receive data, so
  184.     in      al,dx        ; check status to see if any is ready.
  185.     and     al,rcheck    ; get received data bit
  186.     jnz     good_rx         ; yes, go accept the byte
  187.  
  188.     mov     dx,ier        ; look at transmit condition
  189.     in      al,dx        ; to see if we are enabled to send data
  190.     and     al,txint
  191.     jz      int_end        ; not enabled, so go away
  192.     mov     dx,lsr        ; we are enabled, so look for tx condition
  193.     in    al,dx
  194.     and     al,tcheck
  195.     jz    int_end
  196.     jmp    goodtx          ; transmitter is finished, go get more data
  197.  
  198. int_end:
  199.     mov     dx,ocw2        ; tell the 8259 that I'm done
  200.     mov     al,eoi
  201.     out    dx,al
  202.  
  203.     pop     dx
  204.     pop     cx
  205.     pop     bx
  206.     pop     ax
  207.     pop     di
  208.     pop     ds
  209.     pop     bp
  210.     iret
  211. int_hndlr endp
  212.     page
  213. ;
  214. ; init_au(divisor:word)
  215. ; initialize the Intel 8250 and set up interrupt vector to int_hndlr
  216. ; divisor is the divisor for the baud rate generator
  217. ;
  218. init_au    proc    far
  219.     push    bp
  220.     mov     bp,sp
  221.     cli
  222.  
  223.     mov    ax,ds
  224.     mov    cs:dataseg,ax
  225.  
  226. ; reset the UART
  227.     mov     al,0
  228.     mov     dx,mcr
  229.     out    dx,al
  230.  
  231.     mov     dx,lsr        ; reset line status condition
  232.     in    al,dx
  233.     mov     dx,datreg    ; reset recsive data condition
  234.     in    al,dx
  235.     mov     dx,msr        ; reset modem deltas and conditions
  236.     in    al,dx
  237.  
  238. ; set baud rate with the passed argument
  239.     mov     dx,lcr
  240.     mov     al,dla+mode
  241.     out    dx,al
  242.     mov     dx,dll
  243.     mov     al,6[bp]    ; low byte of passed argument
  244.     out    dx,al
  245.     mov     dx,dlh
  246.     mov     al,7[bp]    ; high byte of passed argument
  247.     out    dx,al
  248.  
  249. ; set 8250 to 8 bits, no parity
  250.     mov     dx,lcr
  251.     mov     al,mode
  252.     out    dx,al
  253.  
  254. ; set interrupt vector
  255.     push    ds
  256.     mov     ax,0
  257.     mov     ds,ax
  258.     mov     bx,ds:int_off
  259.     mov     cx,ds:int_off+2
  260.     mov     word ptr ds:int_off,offset int_hndlr
  261.     mov     ds:int_off+2,cs
  262.     pop     d